/*
 * Copyright (C) 2019 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

@file:JvmName("TemplateTestUtils")

package com.android.tools.idea.templates

import com.android.ide.common.repository.AgpVersion
import com.android.sdklib.AndroidMajorVersion
import com.android.sdklib.AndroidVersion
import com.android.sdklib.SdkVersionInfo
import com.android.tools.idea.npw.project.GradleAndroidModuleTemplate.createDefaultModuleTemplate
import com.android.tools.idea.npw.template.ModuleTemplateDataBuilder
import com.android.tools.idea.npw.template.ProjectTemplateDataBuilder
import com.android.tools.idea.templates.KeystoreUtils.getOrCreateDefaultDebugKeystore
import com.android.tools.idea.templates.KeystoreUtils.sha1
import com.android.tools.idea.testing.AgpVersionSoftwareEnvironment
import com.android.tools.idea.testing.resolve
import com.android.tools.idea.util.toIoFile
import com.android.tools.idea.wizard.template.ApiTemplateData
import com.android.tools.idea.wizard.template.Language
import com.android.tools.idea.wizard.template.Template
import com.android.tools.idea.wizard.template.TemplateConstraint
import com.android.tools.idea.wizard.template.ThemesData
import com.android.tools.idea.wizard.template.ViewBindingSupport
import com.intellij.openapi.project.Project
import com.intellij.openapi.project.guessProjectDir
import junit.framework.TestCase.assertTrue
import java.nio.file.Files
import java.nio.file.Path

internal const val SDK_VERSION_FOR_TEMPLATE_TESTS = 35

internal fun verifyLanguageFiles(projectDir: Path, language: Language) {
  // Note: Files.walk() stream needs to be closed (or consumed completely), otherwise it will leave
  // locked directories on Windows
  val allPaths =
    Files.walk(projectDir)
      // Exclude the file generated by using Version Catalogs.
      .filter {
        !it.endsWith("LibrariesForLibs.java") && !it.endsWith("LibrariesForLibsInPluginsBlock.java")
      }
      .toList()
  val wrongLanguageExtension = if (language == Language.Kotlin) ".java" else ".kt"
  assertTrue(
    "Wrong language extension",
    allPaths.none { it.toString().endsWith(wrongLanguageExtension) },
  )
}

// "in" is a kotlin keyword. This is intentional, to make sure templates properly escape it
private const val defaultPackage = "template.test.in"
internal const val defaultModuleName = "Template test module"

internal fun getDefaultModuleState(
  project: Project,
  template: Template,
  agpVersionSoftwareEnvironment: AgpVersionSoftwareEnvironment,
): ModuleTemplateDataBuilder {
  val versions = agpVersionSoftwareEnvironment.resolve()
  // TODO(qumeric): is always new?
  val projectStateBuilder =
    ProjectTemplateDataBuilder(true).apply {
      agpVersion = AgpVersion.parse(versions.agpVersion)
      androidXSupport = true
      setProjectDefaults(project)
      language = Language.Java
      topOut = project.guessProjectDir()!!.toIoFile()
      debugKeyStoreSha1 = sha1(getOrCreateDefaultDebugKeystore())
      applicationPackage = defaultPackage
      overridePathCheck =
        true // To disable android plugin checking for ascii in paths (windows tests)
    }

  val minSdk = template.minSdk.coerceAtLeast(AndroidVersion.VersionCodes.M)
  return ModuleTemplateDataBuilder(
      projectStateBuilder,
      isNewModule = true,
      viewBindingSupport = ViewBindingSupport.SUPPORTED_4_0_MORE,
    )
    .apply {
      name = defaultModuleName
      packageName = defaultPackage
      val paths = createDefaultModuleTemplate(project, name!!).paths
      setModuleRoots(paths, projectTemplateDataBuilder.topOut!!.path, name!!, packageName!!)
      isLibrary = false
      formFactor = template.formFactor
      category = template.category
      isCompose = template.constraints.contains(TemplateConstraint.Compose)
      isMaterial3 = template.constraints.contains(TemplateConstraint.Material3)
      themesData = ThemesData("App")
      apis =
        ApiTemplateData(
          buildApi = AndroidVersion.fromString(versions.compileSdk),
          targetApi = AndroidMajorVersion(versions.targetSdk.toInt()),
          minApi = AndroidMajorVersion(minSdk),
          // The highest supported/recommended appCompat version is P(28)
          appCompatVersion =
            SdkVersionInfo.HIGHEST_KNOWN_STABLE_API.coerceAtMost(AndroidVersion.VersionCodes.P),
        )
    }
}
